import store from '@/store'

import eventBus from './utils/EventBus'
interface Options {
  time?: number
  url?: string
}

async function ping(url: string) {
  const networks = store.getState().networks
  if (networks > 0) {
    return true
  }

  const controller = new AbortController()
  const timeoutId = setTimeout(() => controller.abort(), 5000)
  try {
    const response = await fetch((import.meta.env.VITE_BASE_API as string) + url, {
      method: 'GET',
      signal: controller.signal,
    })
    clearTimeout(timeoutId) // 清除超时定时器

    if (response.ok) {
      console.log(`${url} is reachable.`)
      return true
    } else {
      console.log(`${url} is not reachable. Status: ${response.status}`)
      return false
    }
  } catch (error) {
    clearTimeout(timeoutId) // 清除超时定时器
    console.log(`Error while pinging ${url}: ${error.message}`)
    return false
  }
}

export class Updater {
  oldStatus: boolean | null //存储第一次值也就是script 的hash 信息
  newStatus: boolean //获取新的值 也就是新的script 的hash信息
  dispatch: Record<string, any[]> //小型发布订阅通知用户更新了
  url: string
  time: number
  timer: any
  constructor(options: Options) {
    this.oldStatus = true
    this.newStatus = true
    this.dispatch = {}
    this.time = options?.time
    this.init() //初始化
    this.timing() //轮询
    this.url = options.url
  }

  async init() {
    this.oldStatus = null
  }

  //发布订阅通知
  on(key: 'no-update' | 'update', fn: () => void) {
    ;(this.dispatch[key] || (this.dispatch[key] = [])).push(fn)
    return this
  }

  compare(oldStatus: boolean, newStatus: boolean) {
    // //如果新旧length 一样无更新
    if (oldStatus === newStatus) {
      return
    } else {
      //否则通知更新
      this.dispatch['update'].forEach((fn) => {
        fn(this.newStatus)
      })
      this.oldStatus = this.newStatus
    }
  }

  timing() {
    if (this.timer) {
      clearTimeout(this.timer)
    }
    //轮询
    this.timer = setTimeout(async () => {
      this.newStatus = await ping(this.url)
      eventBus.emit('APPPING', `【ping】${this.url}：${this.newStatus ? 'true' : 'false'}`)
      this.compare(this.oldStatus, this.newStatus)
      this.timing()
    }, this.time)
  }
}
